import React, {
    Fragment,
    PureComponent
} from 'react';

import {
    View,
    Text,
    Dimensions,
    StyleSheet
} from 'react-native';

const {
    width,
    height
} = Dimensions.get(`screen`);

import ItemRow from './item';

import PropTypes from 'prop-types';

import {
    Tip,
    Empty,
    Press,
    Layout,
    Dialog,
    Header,
    Loading
} from './../../../components';

import Upgrade from './upgrade';
import Filter from './../filter';
import * as Iap from './../../../utils/iap';
import Connect from './../../../utils/connect';

import commonAction from './../../../state/actions/common';
import discoverAction from './../../../state/actions/discover';

import * as commonTypes from './../../../state/types/common';
import * as discoverTypes from './../../../state/types/discover';

import CardStack, { Card } from 'react-native-card-stack-swiper';

import filter_icon from './../../../images/home/filter.png';
import like_icon from './../../../images/home/discover/liked.png';
import unlike_icon from './../../../images/home/discover/dislike.png';
import return_icon from './../../../images/home/discover/return.png';

interface Props {
    user:any,
    discover:any,
    commonActions:any,
    discoverActions:any
}

interface State {
    loading:boolean,
    isLastPage:boolean,
    showFilter:boolean
}

@Connect([`user`,`discover`],{
    commonActions:commonAction,
    discoverActions:discoverAction
})
class Discover extends PureComponent<Props,State> {
    private filter:any = null;
    private curPos:number = 0;
    private dialog:boolean = false;

    state = {
        loading:true,
        showFilter:false,
        isLastPage:false
    }

    static contextTypes = {
        listenTabIn:PropTypes.func
    }

    private stack:CardStack|any = {};

    static defaultProps = {
        user:{},
        discover:{},
        commonAction:{},
        discoverActions:{}
    }

    get limit() {
        return 30
    }

    get userState() {
        const {
            user
        } = this.props;
        return user;
    }

    get loginUser() {
        const {
            loginUser
        } = this.userState;
        return loginUser;
    }

    get userId() {
        const {
            userId = 0
        } = this.loginUser;
        return userId;
    }

    get isEmpty() {
        const {
            loading
        } = this.state;
        return !loading && !this.dataSource.length
    }

    get lastId() {
        const {
            length
        } = this.dataSource;
        const {
            searchResultId = 0
        } = this.dataSource[length - 1] || {};
        return searchResultId;
    }

    get dataSource() {
        const {
            discover
        } = this.props;
        const {
            list = []
        } = discover || {};
        return list;
    }

    get commonActions() {
        const {
            commonActions
        } = this.props;
        return commonActions;
    }

    get discoverActions() {
        const {
            discoverActions
        } = this.props;
        return discoverActions;
    }

    componentDidMount() {
        this.onRefresh();
        this.context.listenTabIn(this.onRefresh);
    }

    public onRefresh = () => {
        this.fetchData(0);
    }

    private fetchData = async (
        lastId:number
    ) => {
        const para = {
            lastId:lastId,
            limit:this.limit
        }

        let list = [];
        let success = true;

        this.setState({
            loading:true
        })

        const delay = !!lastId ? 0:350;

        try {
            list = await this.discoverActions[
                discoverTypes.getDiscoverList
            ](para)
        }
        catch (e) {
            success = false;
            Tip.warm({
                message:e.message
            })
        }

        const state:any = {
            loading:false
        }

        if(success) {
            state.isLastPage = (
                list.length < this.limit
            )
        }

        setTimeout(() => {
            this.setState(state)
        },delay)
    }

    private onLikePress = () => {
        this.stack.swipeRight();
    }

    private onDislikePress = () => {
        this.stack.swipeLeft();
    }

    private onRestPress = () => {
        const index = (
            this.curPos - 1
        )

        if(index < 0) {
            return false;
        }

        const {
            userId = 0,
            isLiked = 0
        } = this.dataSource[index] || {};

        if(isLiked === 1 ) {
            this.stack.goBackFromRight();
        }
        else {
            this.stack.goBackFromLeft();
        }

        this.commonActions[
            commonTypes.resetLikeUser
        ](userId);
    }

    private onSwipedLeft = async (
        i:number
    ) => {
        const {
            userId
        } = this.dataSource[i] || {};

        this.onPostAjaxEnd(
            this.commonActions[
                commonTypes.postUnlikeUser
            ](userId,false)
        )
    }

    private onSwipedRight = async (
        i:number
    ) => {
       const {
           userId
       } = this.dataSource[i] || {};

       this.onPostAjaxEnd(
           await this.commonActions[
               commonTypes.postLikeUser
           ](userId,false)
       )
    }

    private onCardChange = (
        i:number
    ) => {
        const {
            length
        } = this.dataSource;

        const {
            isLastPage
        } = this.state;

        this.curPos = i + 1;

        const isLastCard = length - 1 === i;

        if(isLastCard) {
            this.fetchData(
                isLastPage ? 0:this.lastId
            )
        }
    }

    private onPostAjaxEnd = async (
        res:any
    ) => {
        const {
            expire = 0
        } = res || {};

        if(expire <= 0 || this.dialog) {
            return false
        }

        this.dialog = true;

        this.popUpModal(expire);
    }

    private onUpgrade = async () => {
        Iap.buyMember();
    }

    private popUpModal = (
        expire:number
    ) => {
        const content = (
            <Upgrade
                time={expire}
                onUpgrade={this.onUpgrade}
            />
        )

        const _props:any = {
            maskOpacity:.7,
            clickClose:true,
            direction:`center`,
            onClosed:this.onDialogClosed
        }

        Dialog.show(content,_props)
    }

    private onDialogClosed = () => {
        this.dialog = false;
    }

    private renderItem = (
        item:any,i:number
    ) => (
        <Card
            key={i}
            style={styles.cardItem}
            children={<ItemRow data={item} />}
        />
    )

    public onFilterSubmit = () => {
        this.filter.submit();
    }

    private renderRight = () => {
        const {
            showFilter
        } = this.state;

        if(showFilter) {
            return (
                <Press
                    style={styles.doneStyle}
                    onPress={this.onFilterSubmit}
                >
                    <Text style={styles.doneText}>
                        Done
                    </Text>
                </Press>
            )
        }

        return (
            <Press
                source={filter_icon}
                style={styles.filterButton}
                onPress={this.onOpenFilter}
            />
        )
    }

    private onOpenFilter = () => {
        this.setState({
            showFilter:true
        },this.onOpenModal)
    }

    public onOpenModal = () => {
        this.filter.open(this.onRefresh);
    }

    private onCloseState = () => {
        this.setState({
            showFilter:false
        })
    }

    private onCloseFilter = () => {
        this.filter.close();
    }

    get icons() {
        return [
            {
                icon:unlike_icon,
                onPress:this.onDislikePress
            },
            {
                icon:like_icon,
                onPress:this.onLikePress
            },
            {
                icon:return_icon,
                onPress:this.onRestPress
            }
        ]
    }

    get renderContent() {
        const {
            loading
        } = this.state;

        if(loading) {
            return (
                <Loading.Find />
            )
        }

        return (
            <Fragment>
                <CardStack
                    style={styles.content}
                    onSwiped={this.onCardChange}
                    verticalThreshold={width / 3}
                    horizontalThreshold={width / 3}
                    renderNoMoreCards={() => null}
                    onSwipedTop={this.onSwipedLeft}
                    onSwipedLeft={this.onSwipedLeft}
                    onSwipedRight={this.onSwipedRight}
                    onSwipedBottom={this.onSwipedRight}
                    ref={(e:CardStack) => this.stack = e}
                    children={this.dataSource.map(this.renderItem)}
                />
                <View style={styles.footerStyle}>
                    {this.icons.map((item,i) => {
                        return (
                            <Press
                                key={i}
                                source={item.icon}
                                onPress={item.onPress}
                            />
                        )
                    })}
                </View>
            </Fragment>
        )
    }

    render() {
        const {
            showFilter
        } = this.state;
        return (
            <Layout
                close={true}
                scroll={false}
                padding={false}
                title="Discover"
                backShow={showFilter}
                renderRight={this.renderRight}
                onBackPress={this.onCloseFilter}
            >
                <View style={styles.container}>
                    {this.isEmpty ?
                        <Empty
                            onRefresh={this.onRefresh}
                            title="Check later please, there was nobody nearby."
                        /> : this.renderContent
                    }
                </View>
                <Filter
                    ref={e => this.filter = e}
                    onClose={this.onCloseState}
                />
            </Layout>
        )
    }
}

export default Discover;

const styles = StyleSheet.create({
    container:{
        flex:1,
        overflow:`hidden`
    },
    content:{
        flex:1
    },
    cardItem:{
        width:width,
        paddingTop:20,
        paddingHorizontal:12,
        height:height - 186 - Header.height
    },
    footerStyle:{
        height:110,
        alignItems:`center`,
        paddingHorizontal:40,
        flexDirection:`row`,
        justifyContent:`space-between`
    },
    filterButton:{
        height:`100%`,
        paddingLeft:16,
        justifyContent:`center`
    },
    doneText:{
        fontSize:18,
        color:`#fff`,
        fontWeight:`bold`
    },
    doneStyle:{
        height:`100%`,
        paddingLeft:16,
        justifyContent:`center`
    }
}) as any